﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using Autofac;
using Autofac.Integration.Mvc;
using AutoMapper;
using JiaBao.Core.Configuration;
using JiaBao.Core.Infrastructure.DependencyManagement;
using JiaBao.Core.Infrastructure.Mapper;

namespace JiaBao.Core.Infrastructure
{
    /// <summary>
    /// 框架引擎
    /// </summary>
    public class JiaBaoEngine : IEngine
    {
        #region 字段

        private ContainerManager _containerManager;

        #endregion

        #region 属性

        /// <summary>
        /// 依赖注入管理器
        /// </summary>
        public virtual ContainerManager ContainerManager
        {
            get { return _containerManager; }
        }

        #endregion

        /// <summary>
        /// 初始化程序
        /// </summary>
        /// <param name="config"></param>
        public void Initialize(JiaBaoConfig config)
        {
            //依赖注入
            RegisterDependencies(config);

            //对象映射
            RegisterMapperConfiguration(config);

            //启动任务
            //.....
        }

        #region 简单解析

        /// <summary>
        /// 解析
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T Resolve<T>() where T : class
        {
            return ContainerManager.Resolve<T>();
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public object Resolve(Type type)
        {
            return ContainerManager.Resolve(type);
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T[] ResolveAll<T>()
        {
            return ContainerManager.ResolveAll<T>();
        }

        #endregion

        #region 内部方法

        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="config"></param>
        protected virtual void RegisterDependencies(JiaBaoConfig config)
        {
            var builder = new ContainerBuilder();

            #region 单例注册

            //注册配置文件
            builder.RegisterInstance(config).As<JiaBaoConfig>().SingleInstance();

            //注册引擎
            builder.RegisterInstance(this).As<IEngine>().SingleInstance();

            //注册插件查找器
            var typeFinder = new WebAppTypeFinder();
            builder.RegisterInstance(typeFinder).As<ITypeFinder>().SingleInstance();

            #endregion

            #region 注册继承IDependencyRegistrar的依赖注入

            //获取 IDeependencyRegistrar 
            var drTypes = typeFinder.FindClassesOfType<IDependencyRegistrar>();

            //写入list
            var drInstances = new List<IDependencyRegistrar>();
            foreach (var t in drTypes)
                drInstances.Add((IDependencyRegistrar)Activator.CreateInstance(t));

            //排序
            drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();

            //遍历调用注册方法
            foreach (var dependencyRegistrar in drInstances)
            {
                dependencyRegistrar.Register(builder, typeFinder, config);
               // File.WriteAllText( ("C:/ISS/80/log.txt"), dependencyRegistrar.ToString ()  + Environment.NewLine);
            }
        

            #endregion

            //生成
            var container = builder.Build();

            //创建依赖注入管理实例
            this._containerManager = new ContainerManager(container);
            SetDependencyResolver(container);
         
        }

        /// <summary>
        /// 设置程序的依赖注入解析器 (默认MVC)
        /// </summary>
        /// <param name="container"></param>
        protected virtual void SetDependencyResolver(IContainer container)
        {
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }

        /// <summary>
        /// 注册对象映射
        /// </summary>
        /// <param name="config"></param>
        protected virtual void RegisterMapperConfiguration(JiaBaoConfig config)
        {
            
            var typeFinder = new AppDomainTypeFinder();

            //register mapper configurations provided by other assemblies
            var mcTypes = typeFinder.FindClassesOfType<IMapperConfiguration>();
            var mcInstances = new List<IMapperConfiguration>();
            foreach (var mcType in mcTypes)
                mcInstances.Add((IMapperConfiguration)Activator.CreateInstance(mcType));
            //sort
            mcInstances = mcInstances.AsQueryable().OrderBy(t => t.Order).ToList();
            //get configurations
            var configurationActions = new List<Action<IMapperConfigurationExpression>>();
            foreach (var mc in mcInstances)
                configurationActions.Add(mc.GetConfiguration());
            //register
            AutoMapperConfiguration.Init(configurationActions);

        }


        #endregion

    }
}
